using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Gameplay.RTS.ScriptConfig;
using LitJson;
using UnityEngine;
using Yoozoo.Framework.Core;
using Yoozoo.Managers.ResourceManagerV2.Runtime;

namespace Yoozoo.Gameplay.RTS
{
    public class RtsJsonConfigManager:Singleton<RtsJsonConfigManager>
    {
        private Dictionary<int, TSoldiersThrowable> _throwableJsonData;
        private Dictionary<int, FlyTextOffset> _flyTextOffsetData;

        private ResLoader _resLoader;
        private FlyTextConfig config;
        private SoldierAttackActionConfigFather soldierAttackActionConfigFather;
        private Dictionary<int, ISubAction[]> _attackActions;
        private Dictionary<int, SoldierAttackActionConfig> _attackListConfigs;

#if UNITY_EDITOR
        private Dictionary<int, AttackActionInfo[]> _attackActionConfigs;
        private AttackActionConfig[] EditorSoldierAttackConfigs;
#endif

        private AttackActionConfig[] SoldierAttackConfigMap;
        public void LoadConfigAll(ResLoader resLoader,Action onInitConfig)
        {
            _resLoader = resLoader;
            PreloadSoldierEffectParam();
            PreloadFlyTextOffset();
            PreloadSoldierAttackListAction();
            _resLoader.Load(() =>
            {
                PreloadSoldierAttackAction(onInitConfig);
            });
        }

        private void PreloadFlyTextOffset(Action action = null)
        {
            _resLoader.Add2Load("Assets/ResourcesAssets/Config/RTSScriptConfig/flyTextOffset.json",
                (success, name, asset) =>
                {
                    if (success)
                    {
                        var json = asset as TextAsset;
                        if (json)
                        {

                            if (!string.IsNullOrEmpty(json.text))
                            {


                                JsonMapper.RegisterExporter<float>((obj, writer) =>
                                    writer.Write(Convert.ToDouble(obj)));
                                JsonMapper.RegisterImporter<double, float>(input => Convert.ToSingle(input));
                                config = JsonMapper.ToObject<FlyTextConfig>(json.text);


                                if (_flyTextOffsetData == null)
                                {
                                    _flyTextOffsetData =
                                        new Dictionary<int, FlyTextOffset>(config.offsets.Length);
                                }
                                for (int i = 0; i < config.offsets.Length; i++)
                                {
                                    JsonMapper.RegisterExporter<float>((obj, writer) =>
                                        writer.Write(Convert.ToDouble(obj)));
                                    JsonMapper.RegisterImporter<double, float>(input => Convert.ToSingle(input));
                                    var offset = config.offsets[i];
                                    if (_flyTextOffsetData.ContainsKey(offset.type))
                                    {
                                        _flyTextOffsetData[offset.type] = offset;
                                    }
                                    else
                                    {
                                        _flyTextOffsetData.Add(offset.type, offset);
                                    }
                                }
                            }

                            action?.Invoke();
                        }
                    }
                    else
                    {
                        Debug.LogError("load Asset failed : {0} " + name);
                    }
                });
        }


        private void PreloadSoldierAttackListAction(Action action = null)
        {
            _resLoader.Add2Load("Assets/ResourcesAssets/Config/RTSScriptConfig/SoldierAttackActionConfig.json",
                (success, name, asset) =>
                {
                    if (success)
                    {
                        var json = asset as TextAsset;
                        if (json)
                        {
                            var configs = JsonMapper.ToObject<SoldierAttackActionConfigFather>(json.text);
                            soldierAttackActionConfigFather = configs;
                            if (configs != null)
                            {
                                var keyMap = configs.soldierTypeAndAttackActionKeyMap;
                                if (_attackListConfigs == null)
                                {
                                    _attackListConfigs =
                                        new Dictionary<int, SoldierAttackActionConfig>(keyMap.Length);
                                }


                                _attackListConfigs.Clear();

                                for (int i = 0; i < keyMap.Length; i++)
                                {
                                    JsonMapper.RegisterExporter<float>((obj, writer) =>
                                        writer.Write(Convert.ToDouble(obj)));
                                    JsonMapper.RegisterImporter<double, float>(input => Convert.ToSingle(input));
                                    _attackListConfigs.Add(keyMap[i].soldierType,keyMap[i]);
                                }
                                SquareDataManager.Instance.InitSoldierAttackActionConfig(_attackListConfigs);
                            }
                            action?.Invoke();
                        }
                    }
                    else
                    {
                        Debug.LogError("load Asset failed : {0} " + name);
                    }
                });
        }


        /// <summary>
        /// 攻击指令json
        /// </summary>
        /// <param name="action"></param>
        private void PreloadSoldierAttackAction(Action action = null)
        {
            _resLoader.Add2Load("Assets/ResourcesAssets/Config/RTSScriptConfig/AttackAction.json",
                (success, name, asset) =>
                {
                    if (success)
                    {
                        var json = asset as TextAsset;
                        if (json)
                        {
                            ActionFactory factory = new ActionFactory();
                            //加载配置
                            SoldierAttackConfigMap = JsonMapper.ToObject<AttackActionConfig[]>(json.text);

                            if (SoldierAttackConfigMap != null)
                            {
                                if (_attackActions == null)
                                {
                                    _attackActions =
                                        new Dictionary<int, ISubAction[]>(SoldierAttackConfigMap.Length);
                                }
                                else
                                {
                                    _attackActions.Clear();
                                }

                                

#if UNITY_EDITOR
                                if (_attackActionConfigs == null)
                                {
                                    _attackActionConfigs = new Dictionary<int, AttackActionInfo[]>();
                                }
                                else
                                {
                                    _attackActionConfigs.Clear();
                                }
                                
                                EditorSoldierAttackConfigs = SoldierAttackConfigMap;
#endif
                                
                                JsonMapper.RegisterExporter<float>((obj, writer) =>
                                    writer.Write(Convert.ToDouble(obj)));
                                JsonMapper.RegisterImporter<double, float>(input => Convert.ToSingle(input));
                                
                                for (int i = 0; i < SoldierAttackConfigMap.Length; i++)
                                {
                                    var attackCfg = SoldierAttackConfigMap[i];
                                    ISubAction[] actions = new ISubAction[attackCfg.actions.Length];
                                    for (int j = 0; j < attackCfg.actions.Length; j++)
                                    {
                                        var attackAction = attackCfg.actions[j];
                                        var subAction = factory.ConvertAttackActionInfoCfgToSubAction(attackAction);
                                        actions[j] = subAction;
                                    }

                                    _attackActions.Add(attackCfg.actionID, actions);

#if UNITY_EDITOR
                                    _attackActionConfigs.Add(attackCfg.actionID, attackCfg.actions);
#endif
                                }
                            }
                            SquareDataManager.Instance.InitAttackActions();

                            action?.Invoke();
                        }
                    }
                    else
                    {
                        Debug.LogError("load Asset failed : {0} " + name);
                    }
                }).Load();
        }

        //士兵普工特效json
        public void PreloadSoldierEffectParam(Action action = null)
        {
            _resLoader.Add2Load("Assets/ResourcesAssets/Config/RTSScriptConfig/soldiers_throwable.json",
                (success, name, asset) =>
                {
                    if (success)
                    {
                        var json = asset as TextAsset;
                        if (json)
                        {
                            var throwableConfigMap = JsonMapper.ToObject(json.text);

                            if (throwableConfigMap != null)
                            {
                                if (_throwableJsonData == null)
                                {
                                    _throwableJsonData =
                                        new Dictionary<int, TSoldiersThrowable>(throwableConfigMap.Count);
                                }

                                _throwableJsonData.Clear();
                                for (int i = 0; i < throwableConfigMap.Count; i++)
                                {
                                    JsonMapper.RegisterExporter<float>((obj, writer) =>
                                        writer.Write(Convert.ToDouble(obj)));
                                    JsonMapper.RegisterImporter<double, float>(input => Convert.ToSingle(input));
                                    
                                    var throwable = JsonMapper.ToObject<TSoldiersThrowable>(throwableConfigMap[i].ToJson());
                                    _throwableJsonData.Add((int) throwableConfigMap[i]["soldierType"], throwable);
                                }
                            }

                            action?.Invoke();
                        }
                    }
                    else
                    {
                        Debug.LogError("load Asset failed : {0} " + name);
                    }
                });
        }

#if UNITY_EDITOR
        public void ReloadConfigAll()
        {
            _resLoader.Load();
        }
#endif
        public ISubAction[] GetSubActionsById(int id)
        {
            return _attackActions[id];
        }
        // 复制一份存入AttackStateAction中，后面分job处理的时候用
        public Dictionary<int, ISubAction[]> CloneAllSubAction()
        {
            ActionFactory factory = new ActionFactory();
            Dictionary<int, ISubAction[]> result = new Dictionary<int, ISubAction[]>(SoldierAttackConfigMap.Length);
            for (int i = 0; i < SoldierAttackConfigMap.Length; i++)
            {
                var attackCfg = SoldierAttackConfigMap[i];
                ISubAction[] actions = new ISubAction[attackCfg.actions.Length];
                for (int j = 0; j < attackCfg.actions.Length; j++)
                {
                    var attackAction = attackCfg.actions[j];
                    var subAction = factory.ConvertAttackActionInfoCfgToSubAction(attackAction);
                    actions[j] = subAction;
                }

                result.Add(attackCfg.actionID, actions);
            }

            return result;
        }
        public SoldierAttackActionConfig GetAttackActionsConfigsBySoldierType(int soldierType)
        {
            return _attackListConfigs[soldierType];
        }
        public TSoldiersThrowable GetThrowableConfigBySoldierType(int soldierType)
        {
            if (_throwableJsonData == null)
            {
                return new TSoldiersThrowable();
            }

            _throwableJsonData.TryGetValue(soldierType, out var jsonData);
            return jsonData;
        }

        public FlyTextOffset GetFlyTextOffsetByType(int type)
        {
            if (_flyTextOffsetData.TryGetValue(type,out FlyTextOffset cfg))
            {
                return cfg;
            }
            else
            {
                Debug.LogError("飘字无效类型"+type);
                return null;
            }
        }

        public FlyTextConfig GetFlyTextConfig()
        {
            return config;
        }

        public SoldierAttackActionConfigFather GetSoldierAttackActionConfigFather()
        {
            return soldierAttackActionConfigFather;
        }
#if UNITY_EDITOR
        public void ReloadActionConfig(Action action)
        {
            PreloadSoldierAttackListAction(() => { PreloadSoldierAttackAction(action); });
        }
        public void SaveFlyTextOffsetConfig()
        {
            if (_flyTextOffsetData!=null)
            {
                StringBuilder builder = new StringBuilder();
                JsonWriter writer = new JsonWriter(builder);
                writer.PrettyPrint = true;
                JsonMapper.ToJson(config,writer);
                Debug.Log(builder.ToString());

                string path = Application.dataPath + @"\ResourcesAssets\Config\RTSScriptConfig\flyTextOffset.json";
                StreamWriter streamWriter = new StreamWriter(path,false);
                streamWriter.WriteLine(builder.ToString());
                streamWriter.Close();
            }
        }

        public void SaveActionOffsetConfig(AttackActionConfig[] configs)
        {
            if (_attackActionConfigs!=null)
            {
                EditorSoldierAttackConfigs = configs;
                StringBuilder builder = new StringBuilder();
                JsonWriter writer = new JsonWriter(builder);
                writer.PrettyPrint = true;
                JsonMapper.ToJson(EditorSoldierAttackConfigs,writer);
                Debug.Log(builder.ToString());

                string path = Application.dataPath + @"\ResourcesAssets\Config\RTSScriptConfig\AttackAction.json";
                StreamWriter streamWriter = new StreamWriter(path,false);
                streamWriter.WriteLine(builder.ToString());
                streamWriter.Close();
            }
        }

        public void SaveSoldierAttackActionConfig()
        {
            if (_attackActionConfigs!=null)
            {
                SoldierAttackActionConfigFather fatherConfig;
                fatherConfig = soldierAttackActionConfigFather;

                StringBuilder builder = new StringBuilder();
                JsonWriter writer = new JsonWriter(builder);
                writer.PrettyPrint = true;
                fatherConfig.soldierTypeAndAttackActionKeyMap = _attackListConfigs.Values.ToArray();


                JsonMapper.ToJson(fatherConfig,writer);

                Debug.Log(builder.ToString());

                string path = Application.dataPath + @"\ResourcesAssets\Config\RTSScriptConfig\SoldierAttackActionConfig.json";
                StreamWriter streamWriter = new StreamWriter(path,false);
                streamWriter.WriteLine(builder.ToString());
                streamWriter.Close();
            }
        }

        public AttackActionConfig[] GetSubActionsInEditor()
        {
            return EditorSoldierAttackConfigs;
        }

        public  Dictionary<int, SoldierAttackActionConfig> GetSoldierAttackActionConfigInEditor()
        {
            return _attackListConfigs;
        }
#endif


        public override void Dispose()
        {
            _throwableJsonData = null;
            _resLoader = null;
            base.Dispose();
        }
    }
}
